/*
 * Copyright 2010 Christoph Widulle (christoph.widulle@googlemail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */



package com.android1.amarena2d.actions.movement;

import com.android1.amarena2d.actions.base.IntervalAction;
import com.android1.amarena2d.nodes.behavior.ActionTarget;

public class Shake extends IntervalAction {

    public static interface Direction {
        public static final int X = 1;
        public static final int Y = -1;
        public static final int XY = 0;
    }

    private static final float DEFAULT_STRENGHT = 10;
    private static final float[][] DEFAULT_PATTERN_X = new float[][]{
            {Direction.X, -0.1F},
            {Direction.X, 0.1F},
            {Direction.X, -0.9F},
            {Direction.X, 0.9F},
            {Direction.X, -0.7F},
            {Direction.X, 0.7F},
            {Direction.X, -0.8F},
            {Direction.X, 0.8F},
            {Direction.X, -0.6F},
            {Direction.X, 0.6F},
            {Direction.X, -0.5F},
            {Direction.X, 0.5F},
            {Direction.X, -0.4F},
            {Direction.X, 0.4F},
            {Direction.X, -0.3F},
            {Direction.X, 0.3F},
    };

    private static final float[][] DEFAULT_PATTERN_Y = new float[][]{
           {Direction.Y, -0.1F},
            {Direction.Y, 0.1F},
            {Direction.Y, -0.9F},
            {Direction.Y, 0.9F},
            {Direction.Y, -0.7F},
            {Direction.Y, 0.7F},
            {Direction.Y, -0.8F},
            {Direction.Y, 0.8F},
            {Direction.Y, -0.6F},
            {Direction.Y, 0.6F},
            {Direction.Y, -0.5F},
            {Direction.Y, 0.5F},
            {Direction.Y, -0.4F},
            {Direction.Y, 0.4F},
            {Direction.Y, -0.3F},
            {Direction.Y, 0.3F},

    };

    private float[][] pattern;
    private float strenght;

    private int frameCount;
    private int lastFrame = -1;
    private float slice;


    public static Shake $(final float duration) {
        return new Shake(DEFAULT_PATTERN_X, DEFAULT_STRENGHT, duration);
    }

    public static Shake $X(final float duration) {
        return new Shake(DEFAULT_PATTERN_X, DEFAULT_STRENGHT, duration);
    }

    public static Shake $Y(final float duration) {
        return new Shake(DEFAULT_PATTERN_Y, DEFAULT_STRENGHT, duration);
    }

    public static Shake $(final float[][] pattern, final float duration) {
        return new Shake(pattern, DEFAULT_STRENGHT, duration);
    }

    public static Shake $(final float[][] pattern, final float strenght, final float duration) {
        return new Shake(pattern, strenght, duration);
    }

    public static Shake $(final float strenght, final float duration) {
        return new Shake(DEFAULT_PATTERN_X, strenght, duration);
    }

    public static Shake $X(final float strenght, final float duration) {
        return new Shake(DEFAULT_PATTERN_X, strenght, duration);
    }

    public static Shake $Y(final float strenght, final float duration) {
        return new Shake(DEFAULT_PATTERN_Y, strenght, duration);
    }

    public Shake(float[][] pattern, float strenght, float duration) {
        super(duration);
        this.strenght = strenght;
        this.pattern = pattern;
    }

    public Shake reset(final float[][] pattern, final float strenght, final float duration) {
        this.duration = duration;
        this.strenght = strenght;
        this.pattern = pattern;
        return this;
    }


    @Override
    public void start(ActionTarget aTarget) {
        frameCount = pattern.length;
        lastFrame = -1;
        slice = 1.0f / frameCount;
        super.start(aTarget);
    }


    @Override
    public void update(float time) {
        int idx = 0;

        if (time != 0)
            idx = (int) (time / slice);

        if (idx >= frameCount) {
            idx = frameCount - 1;
        }

        if (idx != lastFrame) {
            lastFrame = idx;

            float[] frame = pattern[idx];

            if (frame[0] > 0) {
                //X
                target.addX(frame[1] * strenght);

            } else if (frame[0] < 0) {
                //Y
                target.addY(frame[1] * strenght);
            } else {
                //XY
                target.addXY(frame[1] * strenght, frame[2] * strenght);


            }
        }
    }

    @Override
    public IntervalAction reverse() {
        return Shake.$(pattern, strenght, duration);
    }

    @Override
    public Shake copy() {
        return Shake.$(pattern, strenght, duration);
    }
}
